//你好
const { def, base, intField, setEvent, regFieldGetSet, regEvent } = require("./jsdemo_windows.common.cpp.js");

const input_event = ["onChange"];
const input = String.raw/* cpp */`
  class Input : public Window{
    public:
    Input();
    ~Input();

    void render(int mask);
    void mouseDown(int x, int y, int e);
    void mouseUp(int x, int y, int e);
    void mouseMove(int x, int y, int e);
    void keyEvent(int key, int chr);

    char* value;
    int length;
    int size;
    int cursor;
    int hScroll;

${input_event.map((event)=>`
  JSValue ${event};
`).join("")}

  };

  Input::Input() : Window() {
    width = 100;
    height = 200;
    value = "jfksa\nfejlawaakaka你好kakakakaaaafjl\ndskakaaa\naabbbbbbbbbbaaaaa";
    length = 50;
    size = 1;
    cursor = 0;
    hScroll = 0;
    
${input_event.map((event)=> `
      ${event}.tag = JS_TAG_UNDEFINED;
`).join("")}
  }


  Input::~Input(){
    printf("~Input\n");

    ${input_event.map((event)=>`
      JS_FreeValue(ctx, ${event});
`).join("")}

  }


  void Input::render(int mask){
    if((needRefresh)){
      if((beforeRender.tag & mask)!=JS_TAG_UNDEFINED){
        jsCall(beforeRender);
      }
          
      //no_frame = isDown ? 1 : 0;
      Window::render(0);

      int color = getRGB565(fg_color);
      int bg = getRGB565(bg_color);
      printColor = (color<<16) | bg;

      int shade = getRGB565(0x303030);
      int bright = getRGB565(0x303030);
      paint_pattern(abs_pos_x            , abs_pos_y             ,     2, height, (shade<<16) | bright, 0);
      paint_pattern(abs_pos_x            , abs_pos_y             , width,      2, (shade<<16) | bright, 0);
      paint_pattern(abs_pos_x + width - 2, abs_pos_y             ,     2, height,(bright<<16) |  shade, 0);
      paint_pattern(abs_pos_x            , abs_pos_y + height - 2, width,      2,(bright<<16) |  shade, 0);
      paint_pattern(abs_pos_x + 2        , abs_pos_y + 2         , width-4, height-4, bg, 0);

      int basex = abs_pos_x + 5;
      int basey = abs_pos_y + 5;
      int w = width - 14;
      int h = height - 14;

      int x = 0;
      int y = -hScroll * 16;
        
      IOWR(VGA_BLT, BLT_M_RST_FIFO, 0);
      
      int transparentColor = 0x0001;

      IOWR(VGA_BLT, BLT_S_SWITCH, SWITCH_TRANS_ON_05 | transparentColor);//transparent on
      //IOWR(VGA_BLT, BLT_S_SWITCH, SWITCH_TRANS_OFF_04);//transparent off
      
      int fg = getRGB565(0x000000);

      IOWR(VGA_BLT, BLT_S_SETVAL, (fg<<16) | transparentColor);

      
      for(int i=0;i<length;){
          
        int len;
        unsigned int u = utf8_to_unicode(value + i, &len);

        if(cursor==i){
          int curColor = getRGB565(0xFF0000);
          IOWR(VGA_BLT, BLT_S_DESTX, (int)(x + basex));
          IOWR(VGA_BLT, BLT_S_WIDTH_HEIGHT, 8); // w
          IOWR(VGA_BLT, BLT_S_WIDTH_HEIGHT, 2); // h
          IOWR(VGA_BLT, BLT_S_SETVAL, (curColor<<16) | transparentColor);
          IOWR(VGA_BLT, BLT_S_PATTERN, 0xFFFFFFFF);
          IOWR(VGA_BLT, BLT_M_DESTY_MEMSET_REQ, 14 + y + basey);
          IOWR(VGA_BLT, BLT_S_SETVAL, (fg<<16) | transparentColor);
        }
        
        if(u == 0x0D || u == 0x0A){
        }else if(y>=0 && y<h){

          if(u<0x80){
            putcWinCore(x + basex, y + basey, u, (fg<<16) | transparentColor);
            x+=8;
          }else{
            putcUWinCore(x + basex, y + basey, u, (fg<<16) | transparentColor);
            x+=16;
          }

        }


        if(u==0x0A || x>=w){
          x=0;
          y+=16;
        }

        i+=len;
      }

      //IOWR(VGA_BLT, BLT_S_SWITCH, SWITCH_TRANS_ON_05 | transparentColor);//transparent on
      IOWR(VGA_BLT, BLT_S_SWITCH, SWITCH_TRANS_OFF_04);//transparent off


      if((afterRender.tag & mask)!=JS_TAG_UNDEFINED){
        jsCall(afterRender);
      }
      if(mask){
        needRefresh = 0;
      }
    }

  }

  void Input::mouseDown(int mx, int my, int e){
    //????

    printf("mouseDown,%d,%d\n", mx, my);


    int basex = 5;
    int basey = 5;
    int w = width - 14;
    int h = height - 14;

    int x = 0;
    int y = -hScroll * 16;
      
    for(int i=0;i<length;){

      int len;
      unsigned int u = utf8_to_unicode(value + i, &len);
    
      if(y>=0 && y<h){
        if(mx>=basex+x && mx<=basex+x+8 && my>=basey+y && my<=basey+y+16){
          cursor = i;
          break;
        }
      }
    
      if(u<0x80){
        x+=8;
      }else{
        x+=16;
      }

      if(u==0x0A || x>=w){
        if(mx>=basex+x && my>=basey+y && my<=basey+y+16){
          cursor = i;
          break;
        }
        x=0;
        y+=16;
      }
      i+=len;
    }
    
    needRefresh = 1;
  }
  void Input::mouseUp(int x, int y, int e){
  }
  void Input::mouseMove(int x, int y, int e){
  }
  void Input::keyEvent(int key, int keyChr){
    //????
    //??
    //??
    //printf("fdsa,%08X,%08X\n", key, keyChr);
    if(key==0){
      keyChr = 0;
    }

    int y = -hScroll * 16;
    int w = width - 14;
    switch(key){
    case KEY_ARROW_UP: case KEY_ARROW_DOWN:{
      int x = 0;
      int lpos = 0;
      int flg = 0;
      int currentLine = 0;
      int currentPos = 0;
      int i;
      for(i=0;i<length;){
        if(i>=cursor){
          break;
        }
        int len;
        unsigned int u = utf8_to_unicode(value + i, &len);
        if(u<0x80){
          x+=8;
          currentPos++;
        }else{
          x+=16;
          currentPos+=2;
        }
        if(u==0x0A || x>=w){
          x=0;
          y+=16;
          currentLine++;
          currentPos=0;
        }
        i+=len;
      }

      int targetLine;
      if(key==KEY_ARROW_UP){
        targetLine = currentLine <= 0 ? 0 : currentLine - 1;
      }else{
        targetLine = currentLine + 1;
      }
      int targetPos = currentPos;

      x = 0;
      currentLine = 0;
      currentPos = 0;
      for(i=0;i<length;){
        if((currentLine == targetLine) && (currentPos >= targetPos)){
          break;
        }
        int len;
        unsigned int u = utf8_to_unicode(value + i, &len);
        if(u<0x80){
          x+=8;
          currentPos++;
        }else{
          x+=16;
          currentPos+=2;
        }
        if(u==0x0A || x>=w){
          if(currentLine == targetLine){
            break;
          }
          x=0;
          y+=16;
          currentLine++;
          currentPos=0;
        }
        i+=len;
      }
      cursor = i < length ? i : length - 1;

      break;}
    case KEY_ARROW_LEFT:{
      int len;
      for(int i=0;i<cursor;){
        unsigned int u = utf8_to_unicode(value + i, &len);
        i+=len;
      }
      cursor-=len;
      if(cursor<0)cursor=0;

      break;}
    case KEY_ARROW_RIGHT:{
      int len;
      unsigned int u = utf8_to_unicode(value + cursor, &len);
      cursor+=len;
      if(cursor>=length)cursor=length-1;

      break;}
    }

    
    if(key == KEY_DELETE){
      printf("del\n");
    }

    if(key == KEY_BKSP){
      printf("bs\n");
    }

    if(keyChr){
      printf("-%c-\n", keyChr);
    }


    
    needRefresh = 1;
  }

  ${input_event.map((event)=>{
    return setEvent("Input", "input", event);
  }).join("")}
  

  static JSValue js_input_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) {
    Input* p = new Input();
    JSValue obj = JS_NewObjectClass(ctx, js_input_class_id);
    p->js_obj = obj;
    JS_SetOpaque(obj, p);
    return obj;
  }
  static void js_input_finalizer(JSRuntime *rt, JSValue val) {
    Input *p = (Input*)JS_GetOpaque(val);
    if(p){
      delete p;
    }
  }
  
  static JSValue js_input_get_text(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
      Input *p = (Input*)JS_GetOpaque(this_val);
      if(p){
        // if(p->title){
        //   JS_FreeCString(ctx, p->title);
        // }
        // p->title = (char*)JS_ToCString(ctx, argv[0]);
        // js_input_calc_size(p);
        // p->needRefresh = 1;
      }
      return JS_UNDEFINED;
  }
  static JSValue js_input_set_text(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
      Input *p = (Input*)JS_GetOpaque(this_val);
      if(p){
        // if(p->title){
        //   JS_FreeCString(ctx, p->title);
        // }
        // p->title = (char*)JS_ToCString(ctx, argv[0]);
        // js_input_calc_size(p);
        // p->needRefresh = 1;
      }
      return JS_UNDEFINED;
  }

  void input_init(JSValue* window_ctor, JSValue* window_proto) {
    JS_NewClassID(&js_input_class_id);
    JSClassDef input_def = {
      .class_name = "Input",
      .finalizer = js_input_finalizer,
    };
    JS_NewClass(rt, js_input_class_id, &input_def);

    JSValue input_proto = JS_NewObject(ctx);

    // ?? getter
    JS_DefinePropertyGetSet(ctx, input_proto, JS_NewAtom(ctx, "text"), JS_NewCFunction(ctx, js_input_get_text, "text", 0), JS_NewCFunction(ctx, js_input_set_text, "text", 1), JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE);

    JS_SetClassProto(ctx, js_input_class_id, input_proto);

${input_event.map((event)=>{
  return regEvent("input", "input_proto", event);
}).join("")}

    JSValue input_ctor = JS_NewCFunction2(ctx, js_input_ctor, "Input", 2, JS_CFUNC_constructor, 0);
    JS_SetConstructor(ctx, input_ctor, input_proto);
    JS_SetPropertyStr(ctx, global, "Input", input_ctor);

    JS_SetPrototype(ctx, input_proto, *window_proto);
    JS_SetPrototype(ctx, input_ctor, *window_ctor);
  }  
`;

module.exports = { input };

